/* global Cesium */
import TargetStyle from './TargetStyle';
import check from '../Core/check';
import primitiveType from './primitiveType';

class TargetLayer {
    constructor(viewer) {
        this._show = true;
        this._gid = Cesium.createGuid();
        this.layerConfig = new Map();
        this.earth = viewer;
        // 根节点图层
        this.rootCollection = new Cesium.PrimitiveCollection({
            show: this._show,
        });
        this.earth.scene.primitives.add(this.rootCollection);
        // 点图标图层
        this._pointCollection = new Cesium.PointPrimitiveCollection();
        this.rootCollection.add(this._pointCollection);
        // 文字图层
        this._labelCollection = new Cesium.LabelCollection();
        this.rootCollection.add(this._labelCollection);
        // 图标图层
        this._billboardCollection = new Cesium.BillboardCollection();
        this.rootCollection.add(this._billboardCollection);
        // 模型图层
        this.modelDataSource = new Cesium.CustomDataSource('targetModel');
        this.earth.dataSources.add(this.modelDataSource);
        this._modelCollection = this.modelDataSource.entities;
        // 标记图层
        this.markDataSource = new Cesium.CustomDataSource('targetMark');
        this.earth.dataSources.add(this.markDataSource);
        this._markCollection = this.markDataSource.entities;
        // 目标对象集合
        this.targetCollection = new Map();
        // 初始化样式
        this.defaultStyle = TargetStyle.DefaultStyle();
        this.layerConfig.set('default', this.defaultStyle);
        // 添加动态更新的图层
        this.targetDataSource = new Cesium.CustomDataSource();
        this.markTargetId = [];
        this.earth.dataSources.add(this.targetDataSource);
        // 图层距离控制
        this.displayCondition = {
            pointDisplayCondition: new Cesium.DistanceDisplayCondition(400000),
            iconDisplayCondition: new Cesium.DistanceDisplayCondition(600, 900000),
            labelDisplayCondition: new Cesium.DistanceDisplayCondition(0, 600),
            modelDisplayCondition: new Cesium.DistanceDisplayCondition(0, 1000),
        };
        // 控制实体元素是否显示
        this._pointShow = false;
        this._billboardShow = false;
        this._labelShow = false;
        this._modelShow = false;
        // 更新实体元素是否显示
        this._removeEventListener = this.earth.camera.moveEnd.addEventListener(() => {
            let cameraHeight = Cesium.Cartographic.fromCartesian(this.earth.camera.position).height;
            let style = this.displayCondition;
            this._pointShow =
                style.pointDisplayCondition._far > cameraHeight &&
                style.pointDisplayCondition._near < cameraHeight;
            this._billboardShow =
                style.iconDisplayCondition._far > cameraHeight &&
                style.iconDisplayCondition._near < cameraHeight;
            this._labelShow =
                style.labelDisplayCondition._far > cameraHeight &&
                style.labelDisplayCondition._near < cameraHeight;
            this._modelShow =
                style.modelDisplayCondition._far > cameraHeight &&
                style.modelDisplayCondition._near < cameraHeight;
            this._markShow =
                style.markDisplayCondition._far > cameraHeight &&
                style.markDisplayCondition._near < cameraHeight;
        });
    }
    _getPoint(targetItem) {
        let style = targetItem.style;
        let mColor = style.color;
        return {
            position: targetItem._position,
            id: targetItem._id,
            pixelSize: style.pointSize,
            color: Cesium.Color.fromCssColorString(mColor),
            distanceDisplayCondition: this.displayCondition.pointDisplayCondition,
            outlineColor: Cesium.Color.fromCssColorString(style.pointLineColor),
            outlineWidth: style.pointLineWidth,
        };
    }
    _getLabel(targetItem) {
        return {
            position: targetItem._position,
            text: targetItem.name,
            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
            id: targetItem._id,
            font: targetItem._style.fontSize + 'px ' + targetItem._style.font,
            fillColor: Cesium.Color.fromCssColorString(targetItem._style.fontColor),
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 1.0,
            showBackground: targetItem._style.showBackground,
            backgroundColor: Cesium.Color.fromCssColorString(targetItem._style.fontBackgroundColor),
            backgroundPadding: new Cesium.Cartesian2(10, 6),
            distanceDisplayCondition: this.displayCondition.labelDisplayCondition,
            pixelOffset: new Cesium.Cartesian2(
                targetItem._style.labelOffsetX,
                targetItem._style.labelOffsetY
            ),
        };
    }
    _getBillboard(targetItem) {
        let style = targetItem.style;
        return {
            position: targetItem._position,
            id: targetItem._id,
            pixelOffset: new Cesium.Cartesian2(0, 0),
            eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0),
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            alignedAxis: Cesium.Cartesian3.UNIT_Z,
            rotation: -1 * Cesium.Math.toRadians(targetItem.angle),
            color: Cesium.Color.fromCssColorString(style.color),
            image: style.iconUrl,
            width: style.iconSize,
            height: style.iconSize,
            distanceDisplayCondition: this.displayCondition.iconDisplayCondition,
        };
    }
    _getModel(targetItem) {
        return {
            position: targetItem._position,
            id: targetItem._id,
            model: {
                uri: targetItem.style.modelUrl,
                minimumPixelSize: targetItem.style.modelMinimumPixelSize,
                // color: Cesium.Color.fromCssColorString(mColor),
                maximumScale: targetItem.style.modelMaximumScale,
                orientation: targetItem.angle,
                distanceDisplayCondition: this.displayCondition.modelDisplayCondition,
            },
        };
    }
    _getMark(targetItem) {
        return {
            position: targetItem._position,
            id: targetItem._id,
            ellipse: {
                semiMinorAxis: targetItem.style.markRadius,
                semiMajorAxis: targetItem.style.markRadius,
                height: 0,
                // heightReference: Cesium.HeightReference.NONE,
                material: new Cesium.C_DynamicRippleMaterialProperty({
                    duration: 1,
                    color: Cesium.Color.fromCssColorString(targetItem.style.markColor),
                }),
                distanceDisplayCondition: this.displayCondition.markDisplayCondition,
            },
        };
    }
    // 添加目标渲染对象
    _addTarget(target) {
        primitiveType.forEach(type => {
            if (this[type + 'Show']) {
                target[type] = this[type + 'Collection'].add(target[type]);
                target[type + 'Init'] = true;
            }
        });
        if (this._markShow && this.markTargetId.includes(target._id)) {
            target._mark = this._markCollection.add(target._mark);
            target._markInit = true;
        }
    }

    getStyleByCode(targetItem) {
        let style = targetItem.style;
        if (targetItem.styleCode) {
            let codeStyle = this.layerConfig.get(targetItem.styleCode);
            if (codeStyle) {
                Object.keys(codeStyle).forEach(key => {
                    style[key] = codeStyle[key];
                });
            }
        }
    }
    /**
     * 根据屏幕坐标，点选态势元素
     * @method pick
     * @param x 坐标x
     * @param y 坐标y
     */
    pick(x, y) {
        let pickedObjects = this.earth.scene.pick(new Cesium.Cartesian2(x, y));
        if (pickedObjects && pickedObjects.primitive && pickedObjects.id) {
            let id = pickedObjects.primitive.id;
            let target = this.targetCollection.get(id);
            return target;
        }
    }
    /**
     * 加载图层样式配置信息
     * @method loadStyleConfig
     * @param config 图层样式配置信息
     */
    loadStyleConfig(config) {
        config.styles.forEach(item => {
            this.layerConfig.set(item.code, item.style);
        });
        let condition = config.distanceDisplayCondition;

        if (condition) {
            // 设置显示距离
            this.displayCondition.pointDisplayCondition = new Cesium.DistanceDisplayCondition(
                condition.point[0],
                condition.point[1]
            );
            this.displayCondition.iconDisplayCondition = new Cesium.DistanceDisplayCondition(
                condition.icon[0],
                condition.icon[1]
            );
            this.displayCondition.labelDisplayCondition = new Cesium.DistanceDisplayCondition(
                condition.label[0],
                condition.label[1]
            );
            this.displayCondition.modelDisplayCondition = new Cesium.DistanceDisplayCondition(
                condition.model[0],
                condition.model[1]
            );
            this.displayCondition.markDisplayCondition = new Cesium.DistanceDisplayCondition(
                condition.mark[0],
                condition.mark[1]
            );
        }
    }
    /**
     * 添加目标对象
     * @method add
     * @param  item 目标对象
     * @return
     *
     * ```
     * 示例代码
     * let tTarget = new GV.TargetItem("targetData.id",113.454,36.45,10000,0);
     *  targetLayer.add(tTarget);
     *
     * ```
     */
    add(item) {
        this.getStyleByCode(item);
        item._point = this._getPoint(item);
        item._label = this._getLabel(item);
        item._billboard = this._getBillboard(item);
        item._model = this._getModel(item);
        item._mark = this._getMark(item);
        item._parentLayer = this;
        this.targetCollection.set(item._id, item);
        this._addTarget(item);
        return item;
    }
    /**
     * 通过id获取目标对象
     * @method getItemById
     * @param itemId 目标对象的id
     * @return
     */
    getItemById(itemId) {
        return this.targetCollection.get(itemId);
    }

    setSelectItem(itemId) {
        this.clearSelectItem();
        this.selectListener = this.earth.clock.onTick.addEventListener(() => {
            this.item = this.getItemById(itemId);
            this.item && (this.item.show = Date.now() % 1000 < 500);
        });
        this.timer = setTimeout(() => {
            this.clearSelectItem();
        }, 8000);
    }
    clearSelectItem() {
        this.selectListener && this.selectListener();
        this.selectListener = null;
        this.item && (this.item.show = true);
        this.item = null;
        clearTimeout(this.timer);
        this.timer = null;
    }
    /**
     * 通过删除目标对象
     * @method remove
     * @param  itemId 目标对象的id
     * @return
     */
    remove(value) {
        let itemId;
        if (check.isString(value)) {
            itemId = value;
        } else {
            itemId = value.id;
        }
        let item = this.getItemById(itemId);
        if (item) {
            this.targetCollection.delete(item.id);
            this._labelCollection.remove(item._label);
            this._pointCollection.remove(item._point);
            this._billboardCollection.remove(item._billboard);
            this._modelCollection.remove(item._model);
            this._markCollection.remove(item._mark);
        }
        return item;
    }
    /**
     * 清空目标对象
     * @method removeAll
     * @return {Boolean}
     */
    removeAll() {
        this.targetCollection.clear();
        this._labelCollection.removeAll();
        this._pointCollection.removeAll();
        this._billboardCollection.removeAll();
        this._modelCollection.removeAll();
        this._markCollection.removeAll();
        return true;
    }
    /**
     * 销毁对象
     */
    destroy() {
        this._removeEventListener();
        this.removeAll();
        this.selectListener && this.selectListener();
        this.earth.dataSources.remove(this.modelDataSource);
        this.modelDataSource.destroy();
        this.modelDataSource = null;

        this.earth.dataSources.remove(this.markDataSource);
        this.markDataSource.destroy();
        this.markDataSource = null;

        this.earth.scene.primitives.remove(this.rootCollection);
        this.rootCollection.destroy();
        this.rootCollection = null;
    }

    /**
     * 判断目标是否存在
     * @method isExist
     * @param itemId 目标对象的ID
     * @return
     */
    isExist(itemId) {
        return this.getItemById(itemId) ? true : false;
    }
    get show() {
        return this.rootCollection.show;
    }
    set show(val) {
        this.rootCollection.show = val;
        this.modelCollection.show = val;
    }
    get id() {
        return this._gid;
    }
    get name() {
        return '目标图层';
    }
}
export default TargetLayer;
